package com.nageoffer.shortlink.project.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nageoffer.shortlink.project.common.constant.RedisKeyConstant;
import com.nageoffer.shortlink.project.common.constant.ShortLinkConstant;
import com.nageoffer.shortlink.project.common.convention.exception.ClientException;
import com.nageoffer.shortlink.project.common.convention.exception.ServiceException;
import com.nageoffer.shortlink.project.common.enums.ValidDateTypeEnum;
import com.nageoffer.shortlink.project.config.RBloomFilterConfiguration;
import com.nageoffer.shortlink.project.dao.entity.*;
import com.nageoffer.shortlink.project.dao.mapper.*;
import com.nageoffer.shortlink.project.dto.req.ShortLinkCreateReqDto;
import com.nageoffer.shortlink.project.dto.req.ShortLinkPageReqDTO;
import com.nageoffer.shortlink.project.dto.req.ShortLinkUpdateReqDto;
import com.nageoffer.shortlink.project.dto.resp.ShortLinkCountQueryReqDTO;
import com.nageoffer.shortlink.project.dto.resp.ShortLinkCreateRespDTO;
import com.nageoffer.shortlink.project.dto.resp.ShortLinkPageRespDTO;
import com.nageoffer.shortlink.project.service.ShortLinkService;
import com.nageoffer.shortlink.project.util.HashUtil;
import com.nageoffer.shortlink.project.util.LinkUtil;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Time;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 短链接接口实现层
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ShortLinkServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLinkDo> implements ShortLinkService  {

    private final RBloomFilter<String> shortUrlCreateCachePenetrationBloomFilter;

    private final ShortLinkMapper shortLinkMapper;

    private final ShortLinkGotoMapper shortLinkGotoMapper;

    private final StringRedisTemplate stringRedisTemplate;

    private final RedissonClient redissonClient;
    private final LinkAccessStatsMapper linkAccessStatsMapper;
    private final LinkLocaleStatsMapper linkLocaleStatsMapper;
    private final LinkOsStatsMapper linkOsStatsMapper;
    private final LinkBrowserStatsMapper linkBrowserStatsMapper;
    private final LinkAccessLogsMapper linkAccessLogsMapper;
    private final LinkDeviceStatsMapper linkDeviceStatsMapper;
    private final LinkNetworkStatsMapper linkNetworkStatsMapper;
    private final LinkStatsTodayMapper linkStatsTodayMapper;

    @Value("${short-link.stats.locale.amap-key}")
    private String statsLocaleMapKey;


    /**
     * 创建短链接
     * @param shortLinkCreateReqDto
     * @return
     */
    @Override
    public ShortLinkCreateRespDTO createShortLink(ShortLinkCreateReqDto shortLinkCreateReqDto) {
        String shortLinkSuffix = generateSuffix(shortLinkCreateReqDto);

        String fullShortUrl = StrBuilder.create(shortLinkCreateReqDto.getDomain())
                .append("/")
                .append(shortLinkSuffix)
                .toString();

        ShortLinkDo shortLinkDo = ShortLinkDo.builder()
                .domain(shortLinkCreateReqDto.getDomain())
                .originUrl(shortLinkCreateReqDto.getOriginUrl())
                .gid(shortLinkCreateReqDto.getGid())
                .createdType(shortLinkCreateReqDto.getCreatedType())
                .validDate(shortLinkCreateReqDto.getValidDate())
                .validDateType(shortLinkCreateReqDto.getValidDateType())
                .miaoshu(shortLinkCreateReqDto.getMiaoshu())
                .shortUri(shortLinkSuffix)
                .enableStatus(0)
                .totalPv(0)
                .totalUip(0)
                .totalUv(0)
                .favicon(getFavicon(shortLinkCreateReqDto.getOriginUrl()))
                .fullShortUrl(fullShortUrl)
                .build();
        ShortLinkGotoDo shortLinkGotoDo = ShortLinkGotoDo.builder()
                .gid(shortLinkCreateReqDto.getGid())
                .fullShortUrl(fullShortUrl)
                .build();
        try{
            baseMapper.insert(shortLinkDo);
            shortLinkGotoMapper.insert(shortLinkGotoDo);

        }catch (DuplicateKeyException e){
            LambdaQueryWrapper<ShortLinkDo> eq = Wrappers.lambdaQuery(ShortLinkDo.class)
                    .eq(ShortLinkDo::getFullShortUrl, fullShortUrl);
            ShortLinkDo shortLinkDo1 = baseMapper.selectOne(eq);
            if (shortLinkDo1!= null){
                log.warn("重复入库：{}",fullShortUrl);
                throw new ServiceException("短链接生成重复");
            }
        }
        //缓存预热
        stringRedisTemplate.opsForValue()
                .set(String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY,fullShortUrl)
                        ,shortLinkCreateReqDto.getOriginUrl()
                        , LinkUtil.getLinkCacheValidDate(shortLinkCreateReqDto.getValidDate()),TimeUnit.MICROSECONDS);
        shortUrlCreateCachePenetrationBloomFilter.add(fullShortUrl);
        return ShortLinkCreateRespDTO.builder()
                 .fullShortUrl("http://"+shortLinkDo.getFullShortUrl())
                 .originUrl(shortLinkDo.getOriginUrl())
                 .gid(shortLinkCreateReqDto.getGid())
                 .build();

    }




    /**
     * 生成后缀
     * @param shortLinkCreateReqDto
     * @return
     */
    private String generateSuffix(ShortLinkCreateReqDto shortLinkCreateReqDto) {
        int customGenerateCount = 0;
        String shortUrl;
        while (true){
            if (customGenerateCount>10){
                    throw new ServiceException("短链接生成频繁");
            }
            String originUrl = shortLinkCreateReqDto.getOriginUrl();
            originUrl += System.currentTimeMillis();
            shortUrl = HashUtil.hashToBase62(originUrl);
            if (!shortUrlCreateCachePenetrationBloomFilter.contains(shortLinkCreateReqDto.getDomain()+"/"+shortUrl)){
                break;
            }
            customGenerateCount++;
        }

        return shortUrl;
        }

    /**
     * 分页查询短链接
     * @param requestParam
     * @return
     */
    public IPage<ShortLinkPageRespDTO> pageShortLink(ShortLinkPageReqDTO requestParam) {
        LambdaQueryWrapper<ShortLinkDo> eq = Wrappers.lambdaQuery(ShortLinkDo.class)
                .eq(requestParam.getGid() != null, ShortLinkDo::getGid, requestParam.getGid())
                .eq(ShortLinkDo::getEnableStatus, 0)
                .eq(ShortLinkDo::getDelFlag, 0);
        //查数据库数据肯定是shortlinkDo
        IPage<ShortLinkDo> resultPage= baseMapper.selectPage(requestParam, eq);

        return resultPage.convert(each -> {
            ShortLinkPageRespDTO result = BeanUtil.toBean(each, ShortLinkPageRespDTO.class);
            result.setDomain("http://"+result.getDomain());
            return result;
        });

    }

    /**
     * 查询分组下短链接个数
     * @param requestParam
     * @return
     */
    @Override
    public List<ShortLinkCountQueryReqDTO> listGroupShortLinkCount(List<String> requestParam) {
        QueryWrapper<ShortLinkDo> queryWrapper = Wrappers.query(new ShortLinkDo())
                .select("gid as gid,count(*) as shortLinkCount")
                .in("gid",requestParam)
                .eq("enable_status",0)
                .groupBy("gid");
        List<Map<String, Object>> shortLinkDoList = baseMapper.selectMaps(queryWrapper);
        return BeanUtil.copyToList(shortLinkDoList,ShortLinkCountQueryReqDTO.class);
    }

    /**
     * 修改短链接参数
     * @param requestParam
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateShortLink(ShortLinkUpdateReqDto requestParam) {
        LambdaQueryWrapper<ShortLinkDo> queryWrapper = Wrappers.lambdaQuery(ShortLinkDo.class)
                .eq(ShortLinkDo::getGid, requestParam.getGid())
                .eq(ShortLinkDo::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDo::getDelFlag, 0)
                .eq(ShortLinkDo::getEnableStatus, 0);
        ShortLinkDo hasShortLinkDo = baseMapper.selectOne(queryWrapper);

        if (hasShortLinkDo==null){
            throw new ClientException("短链接不存在");
        }

        if (hasShortLinkDo!=null){
            ShortLinkDo shortLinkDo = ShortLinkDo.builder()
                    .domain(hasShortLinkDo.getDomain())
                    .shortUri(hasShortLinkDo.getShortUri())
                    .clickNum(hasShortLinkDo.getClickNum())
                    .favicon(hasShortLinkDo.getFavicon())
                    .createdType(hasShortLinkDo.getCreatedType())
                    .gid(hasShortLinkDo.getGid())
                    .originUrl(requestParam.getOriginUrl())
                    .miaoshu(requestParam.getMiaoshu())
                    .validDateType(requestParam.getValidDateType())
                    .validDate(requestParam.getValidDate())
                    .build();
            if (Objects.equals(hasShortLinkDo.getGid(),requestParam.getGid())){
                LambdaUpdateWrapper<ShortLinkDo> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDo.class)
                        .eq(ShortLinkDo::getFullShortUrl, requestParam.getFullShortUrl())
                        .eq(ShortLinkDo::getGid, requestParam.getGid())
                        .eq(ShortLinkDo::getDelFlag, 0)
                        .eq(ShortLinkDo::getEnableStatus, 0)
                        .set(Objects.equals(requestParam.getValidDateType(), ValidDateTypeEnum.PERMANENT.getType()), ShortLinkDo::getValidDate, null);
                baseMapper.update(shortLinkDo,updateWrapper);
            }
            else {
                LambdaUpdateWrapper<ShortLinkDo> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDo.class)
                        .eq(ShortLinkDo::getFullShortUrl, requestParam.getFullShortUrl())
                        .eq(ShortLinkDo::getGid, hasShortLinkDo.getGid())
                        .eq(ShortLinkDo::getDelFlag, 0)
                        .eq(ShortLinkDo::getEnableStatus, 0)
                        .set(Objects.equals(requestParam.getValidDateType(), ValidDateTypeEnum.PERMANENT.getType()), ShortLinkDo::getValidDate, null);
                baseMapper.delete(updateWrapper);
                shortLinkDo.setGid(requestParam.getGid());
                baseMapper.insert(shortLinkDo);


            }

        }
    }


    /**
     * 短链接跳转
     * @param shortUri 短链接后缀
     * @param request   请求
     * @param response  响应
     */
    @SneakyThrows
    @Override
    public void restoreUrl(String shortUri, ServletRequest request, ServletResponse response) {
        String serverName = request.getServerName();
        String fullShortUrl = serverName+"/"+shortUri;
        String originalLink = stringRedisTemplate.opsForValue().get(String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY, fullShortUrl));
        //先看redis有没有缓存
        if (StrUtil.isNotBlank(originalLink)){
            shortLinkStats(fullShortUrl,null,request,response);
            ((HttpServletResponse) response).sendRedirect(originalLink);
            return;

        }
        boolean contains = shortUrlCreateCachePenetrationBloomFilter.contains(fullShortUrl);
        if (!contains){
            ((HttpServletResponse) response).sendRedirect("/page/notfound");
            return;
        }
        String gotoIsNullShortLink = stringRedisTemplate.opsForValue().get(String.format(RedisKeyConstant.GOTO_IS_NULL_SHORT_LINK_KEY, fullShortUrl));
        if (StrUtil.isNotBlank(gotoIsNullShortLink)){
            ((HttpServletResponse) response).sendRedirect("/page/notfound");
            return;
        }
        RLock lock = redissonClient.getLock(String.format(RedisKeyConstant.LOCK_GOTO_SHORT_LINK_KEY, fullShortUrl));
        lock.lock();
        try {
            shortLinkStats(fullShortUrl,null,request,response);
            originalLink = stringRedisTemplate.opsForValue().get(String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY, fullShortUrl));
            if (StrUtil.isNotBlank(originalLink)){
                ((HttpServletResponse) response).sendRedirect(originalLink);
                return;
            }
            LambdaQueryWrapper<ShortLinkGotoDo> linkGotoQueryWrapper = Wrappers.lambdaQuery(ShortLinkGotoDo.class)
                    .eq(ShortLinkGotoDo::getFullShortUrl, fullShortUrl);
            ShortLinkGotoDo shortLinkGotoDo = shortLinkGotoMapper.selectOne(linkGotoQueryWrapper);
            if (shortLinkGotoDo==null){
                stringRedisTemplate.opsForValue().set(String.format(RedisKeyConstant.GOTO_IS_NULL_SHORT_LINK_KEY,fullShortUrl),"-");
                ((HttpServletResponse) response).sendRedirect("/page/notfound");
                return ;

            }
            LambdaQueryWrapper<ShortLinkDo> shortLinkDoLambdaQueryWrapper = Wrappers.lambdaQuery(ShortLinkDo.class)
                    .eq(ShortLinkDo::getGid, shortLinkGotoDo.getGid())
                    .eq(ShortLinkDo::getFullShortUrl, fullShortUrl)
                    .eq(ShortLinkDo::getDelFlag, 0)
                    .eq(ShortLinkDo::getEnableStatus, 0);
            ShortLinkDo shortLinkDo = baseMapper.selectOne(shortLinkDoLambdaQueryWrapper);

                if (shortLinkDo==null || shortLinkDo.getValidDate().before(new Date())){
                    stringRedisTemplate.opsForValue().set(String.format(RedisKeyConstant.GOTO_IS_NULL_SHORT_LINK_KEY,fullShortUrl),"-");
                    ((HttpServletResponse) response).sendRedirect("/page/notfound");
                    return ;
                }


                stringRedisTemplate.opsForValue().set(
                        String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY,fullShortUrl),
                        shortLinkDo.getOriginUrl(),
                        LinkUtil.getLinkCacheValidDate(shortLinkDo.getValidDate()),TimeUnit.MICROSECONDS
                );
                shortLinkStats(fullShortUrl,shortLinkDo.getGid(),request,response);
                ((HttpServletResponse) response).sendRedirect(shortLinkDo.getOriginUrl());

        }
        finally {
            lock.unlock();
        }

    }

    /**
     * 获得当前的监控数据
     * @param request
     * @param response
     */
    private void shortLinkStats(String fullShortUrl,String gid,ServletRequest request, ServletResponse response) {
        AtomicBoolean uvFirstFlag = new AtomicBoolean();
        Cookie[] cookies = ((HttpServletRequest) request).getCookies();
        try {
            AtomicReference<String> uv = new AtomicReference<>();
            //限制up的查询
            Runnable addResponseCookieTask = ()->{
                uv.set(UUID.fastUUID().toString());
                Cookie uvCookie = new Cookie("uv",uv.get());
                uvCookie.setMaxAge(60*60*24*30);
                uvCookie.setPath(StrUtil.sub(fullShortUrl,fullShortUrl.indexOf("/"),fullShortUrl.length()));
                ((HttpServletResponse)response).addCookie(uvCookie);
                uvFirstFlag.set(Boolean.TRUE);
                stringRedisTemplate.opsForSet().add("short-link:stats:uv:"+fullShortUrl,uv.get());
            };
            //查询cookie是否存在
            if (ArrayUtil.isNotEmpty(cookies)){
                Arrays.stream(cookies)
                        .filter(each -> Objects.equals(each.getName(),"uv"))
                        .findFirst()
                        .map(Cookie::getValue)
                        .ifPresentOrElse(each->{
                            uv.set(each);
                            Long uvAdd = stringRedisTemplate.opsForSet().add("short-link:stats:uv:" + fullShortUrl , each);
                            uvFirstFlag.set(uvAdd!=null && uvAdd>0L);
                            }, addResponseCookieTask);
                } else {
                    addResponseCookieTask.run();
                }
            //限制uip的查询
            String remoteAddr = LinkUtil.getRealIp((HttpServletRequest) request);
            Long uipAdd = stringRedisTemplate.opsForSet().add("short-link:stats:uip:" + fullShortUrl, remoteAddr);
            boolean uipFirstFlag = uipAdd !=null && uipAdd>0;

            if (StrUtil.isBlank(gid)) {
                    LambdaQueryWrapper<ShortLinkGotoDo> eq = Wrappers.lambdaQuery(ShortLinkGotoDo.class)
                            .eq(ShortLinkGotoDo::getFullShortUrl, fullShortUrl);
                    ShortLinkGotoDo shortLinkGotoDo = shortLinkGotoMapper.selectOne(eq);
                    gid = shortLinkGotoDo.getGid();
                }
                int hour = DateUtil.hour(new Date(), true);
                Week week = DateUtil.dayOfWeekEnum(new Date());
                int weekValue = week.getIso8601Value();
                //构建linkaccessstatsdo对象
                LinkAccessStatsDo linkAccessStatsDo = LinkAccessStatsDo.builder()
                        .pv(1)
                        .uv(uvFirstFlag.get() ? 1 : 0)
                        .uip(uipFirstFlag? 1:0)
                        .hour(hour)
                        .fullShortUrl(fullShortUrl)
                        .gid(gid)
                        .date(new Date())
                        .weekday(weekValue)
                        .build();
                linkAccessStatsMapper.shortLinkStats(linkAccessStatsDo);

            //地区统计
            Map<String,Object> localeParamMap = new HashMap<>();
            localeParamMap.put("key",statsLocaleMapKey);
            localeParamMap.put("ip",remoteAddr);
            String localResultStr = HttpUtil.get(ShortLinkConstant.AMAP_REMOTE_URL, localeParamMap);
            JSONObject localeResultObj = JSON.parseObject(localResultStr);
            String infocode = localeResultObj.getString("infocode");
            LinkLocaleStatsDo linkLocaleStatsDo;
            String actualProvince = null;
            String actualCity = null;
            if (StrUtil.isNotBlank(infocode) && StrUtil.equals(infocode,"10000")){
                String province  = localeResultObj.getString("province");
                boolean unknownFlag= StrUtil.equals(province,"[]");
                 linkLocaleStatsDo = LinkLocaleStatsDo.builder()
                         .province(actualProvince = unknownFlag? "未知":province)
                         .city(actualCity = unknownFlag?"未知":localeResultObj.getString("city"))
                         .adcode(unknownFlag? "未知":localeResultObj.getString("adcode"))
                         .cnt(1)
                         .country("中国")
                         .date(new Date())
                         .fullShortUrl(fullShortUrl)
                         .gid(gid)
                         .build();
                linkLocaleStatsMapper.shortLinkLocaleStats(linkLocaleStatsDo);
            }
            // 操作系统统计
            String os = LinkUtil.getClientOS((HttpServletRequest) request);
            LinkOsStatsDo linkOsStatsDo = LinkOsStatsDo.builder()
                    .os(os)
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .cnt(1)
                    .date(new Date())
                    .build();
            linkOsStatsMapper.shortLinkOsStats(linkOsStatsDo);
            //浏览器统计
            String browser = LinkUtil.getClientBrowser((HttpServletRequest) request);
            LinkBrowserStatsDo linkBrowserStatsDo = LinkBrowserStatsDo.builder()
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .browser(browser)
                    .cnt(1)
                    .date(new Date())
                    .build();
            linkBrowserStatsMapper.shortLinkBrowserStats(linkBrowserStatsDo);


            //设备统计
            String device = LinkUtil.getDevice((HttpServletRequest) request);
            LinkDeviceStatsDO linkDeviceStatsDO = LinkDeviceStatsDO.builder()
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .device(device)
                    .cnt(1)
                    .date(new Date())
                    .build();
            linkDeviceStatsMapper.shortLinkDeviceStats(linkDeviceStatsDO);

            //网络统计
            String network = LinkUtil.getNetwork((HttpServletRequest) request);
            LinkNetworkStatsDO linkNetworkStatsDO = LinkNetworkStatsDO.builder()
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .network(network)
                    .cnt(1)
                    .date(new Date())
                    .build();
            linkNetworkStatsMapper.shortLinkNetworkStats(linkNetworkStatsDO);

            //logs统计
            LinkAccessLogsDo linkAccessLogsDo = LinkAccessLogsDo.builder()
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .ip(remoteAddr)
                    .browser(browser)
                    .os(os)
                    .user(uv.get())
                    .network(network)
                    .device(device)
                    .locale(actualProvince+actualCity)
                    .createTime(new Date())
                    .delFlag(0)
                    .build();
            linkAccessLogsMapper.insert(linkAccessLogsDo);
            baseMapper.incrementStats(gid,fullShortUrl,1,uvFirstFlag.get()?1:0,uipFirstFlag?1:0);
            //今日访问统计
            LinkStatsTodayDO build = LinkStatsTodayDO.builder()
                    .date(new Date())
                    .gid(gid)
                    .fullShortUrl(fullShortUrl)
                    .todayPv(1)
                    .todayUv(uvFirstFlag.get() ? 1 : 0)
                    .todayUip(uipFirstFlag ? 1 : 0)
                    .build();
            linkStatsTodayMapper.shortLinkTodayStats(build);



        }
        catch(Throwable e){
                log.error("短链接访问量统计异常", e);
            }
        }



    /**
     * 取得网页的图标
     * @return
     */
    @SneakyThrows
    public String getFavicon(String url){
        URL targetUrl = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection();
        connection.setRequestMethod("GET");
        connection.connect();
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK){
            Document document = Jsoup.connect(url).get();
            Element faviconLink = document.select("link[rel~=(?i)^(shortcut )?icon]").first();
            if (faviconLink!=null){
                return faviconLink.attr("abs:href");
            }
        }
        return null;
    }



}
